package com.fanketly.musicdiary.ui.components

import androidx.compose.animation.*
import androidx.compose.animation.core.keyframes
import androidx.compose.animation.core.tween
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.shadow
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.util.fastForEachIndexed
import androidx.hilt.navigation.compose.hiltViewModel
import coil.compose.AsyncImage
import coil.compose.rememberAsyncImagePainter
import com.fanketly.musicdiary.R
import com.fanketly.musicdiary.domain.MusicViewModel
import com.fanketly.musicdiary.ui.theme.*
import com.google.accompanist.pager.ExperimentalPagerApi
import com.google.accompanist.pager.PagerState

val bottomItemList = listOf(
    Pair(R.string.calendar, Icons.Filled.EditCalendar),
    Pair(R.string.diary, Icons.Filled.FeaturedPlayList),
    Pair(R.string.music, Icons.Filled.MusicNote)
)

@ExperimentalPagerApi
@Composable
fun MyBottomNavigation(
    modifier: Modifier,
    selectedIndex: Int,
    onItemClick: (index: Int) -> Unit
) {
    MyBottomAppBar(
        modifier = modifier.height(56.dp),
        backgroundColor = BlackBottomBackground,
        contentColor = MaterialTheme.colors.onSurface,
        elevation = 4.dp,
        cutoutShape = CircleShape
    ) {
        bottomItemList.fastForEachIndexed { index, item ->
            MyBottomNavigationItem(
                selectedIndex == index,
                stringResource(id = item.first),
                item.second,
                onItemClick = {
                    onItemClick(index)
                }
            )
        }
        Spacer(modifier = Modifier.weight(1f))
    }

}

@Composable
fun RowScope.MyBottomNavigationItem(
    selected: Boolean,
    text: String,
    imageVector: ImageVector,
    contentDescription: String? = null,
    onItemClick: () -> Unit
) {
    BottomNavigationItem(
        unselectedContentColor = SecondaryVariantColor,
        selectedContentColor = SecondaryColor,
        selected = selected,
        alwaysShowLabel = false,
        onClick = onItemClick,
        icon = { MyBottomNavigationIcon(imageVector, contentDescription) },
        label = { MyBottomNavigationText(text) }
    )
}

@Composable
fun MyBottomNavigationText(text: String) {
    Text(text = text)
}

@Composable
fun MyBottomNavigationIcon(imageVector: ImageVector, contentDescription: String? = null) {
    Icon(imageVector = imageVector, contentDescription = contentDescription)
}


@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MusicContentBottom(musicViewModel: MusicViewModel = hiltViewModel()) {
    AnimatedVisibility(
        visible = musicViewModel.isPlaying && musicViewModel.isShowSongDetail,
        enter = fadeIn(),
        exit = fadeOut()
    ) {
        MyBottomAppBar(
            Modifier
                .height(56.dp)
                .fillMaxWidth(),
            backgroundColor = BlackBottomBackground,
            elevation = 0.dp,
            cutoutShape = CircleShape,
            cutoutShapeTop = false
        ) {
            musicViewModel.musicInfo?.let {
                Column(
                    modifier = Modifier
                        .padding(4.dp),
                    verticalArrangement = Arrangement.Center
                ) {
                    Text(
                        text = it.songName,
                        fontSize = 14.sp,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                        color = TextWhite
                    )
                    Text(text = it.artist, fontSize = 12.sp, color = H2Color)
                }
            }
        }
    }
}

@OptIn(ExperimentalAnimationApi::class)
@Composable
fun MusicBottom(musicViewModel: MusicViewModel = hiltViewModel()) {
    Row(
        modifier = Modifier
            .padding(
                start = MediumDimen,
                end = MediumDimen,
                bottom = MediumDimen,
                top = SmallDimen
            )
            .shadow(4.dp, RoundedCornerShape(20.dp))
            .background(BlackBottomBackground)
            .wrapContentWidth(),
        verticalAlignment = Alignment.CenterVertically
    ) {
//        MusicImageAndProgress()
        AnimatedContent(
            targetState = musicViewModel.isPlaying,
            transitionSpec = {
                //tween The first parameter completes the animation for the duration, the second delays the execution
                //with Group the two animations into a ContentTransform, which defines how the content enters and exits
                //using Customize the SizeTransform of a given ContentTransform, which defines how to transform from one size to another when the size of the content changes
                slideInVertically(animationSpec = tween(250, 350)) with
                        slideOutVertically(animationSpec = tween(250)) using
                        SizeTransform { initialSize, targetSize ->
                            if (targetState) {
                                //Create a Keyframes Spec animation and animate according to the values defined by different timestamps (ie different keyframes) in the animation duration
                                keyframes {
                                    // Expand horizontally first.
                                    //at Used to make the animation at this value at the specified time, that is, it should reach this size at 300 milliseconds
                                    IntSize(targetSize.width, initialSize.height) at 300
                                    //字面意思，持续时间
                                    durationMillis = 400
                                }
                            } else {
                                keyframes {
                                    // Shrink vertically first.
                                    IntSize(initialSize.width, targetSize.height) at 300
                                    durationMillis = 400
                                }
                            }
                        }
            }, contentAlignment = Alignment.Center
        ) { targetExpanded ->
            Row(verticalAlignment = Alignment.CenterVertically) {
                if (targetExpanded) {
                    musicViewModel.musicInfo?.let {
                        Column(
                            modifier = Modifier
                                .weight(2f)
                                .padding(4.dp),
                            verticalArrangement = Arrangement.Center
                        ) {
                            Text(
                                text = it.songName,
                                fontSize = 14.sp,
                                maxLines = 1,
                                overflow = TextOverflow.Ellipsis,
                                color = TextWhite
                            )
                            Text(text = it.artist, fontSize = 12.sp, color = TextWhite)
                        }
                    }

                    Icon(
                        modifier = Modifier
                            .size(42.dp)
                            .clickable {
                                musicViewModel.pauseOrRestoreMusic()
                            },
                        imageVector = if (musicViewModel.isPlaying) Icons.Filled.PauseCircleOutline
                        else Icons.Filled.PlayCircleOutline,
                        tint = ImageColor,
                        contentDescription = stringResource(id = R.string.music)
                    )
                }
            }
        }
    }
}


@Composable
fun MusicImageAndProgress(
    page: Int,
    isTodayAdded: Boolean,
    viewModel: MusicViewModel = hiltViewModel(),
    onClick: () -> Unit
) {
    Surface(
        shape = CircleShape,
        modifier = Modifier
            .size(46.dp),
        elevation = 4.dp
    ) {
        if (page == 0) Icon(
            if (isTodayAdded) Icons.Filled.Edit else Icons.Filled.Add, tint = Color.White,
            modifier = Modifier
                .size(42.dp)
                .background(SecondaryColor)
                .clickable { onClick.invoke() },
            contentDescription = null
        )
        else {
            AsyncImage(
                model = if (!viewModel.isPlaying) R.drawable.ic_baseline_play_circle_outline_48
                else viewModel.musicInfo?.songCover ?: R.drawable.ic_not_photo,
                contentDescription = stringResource(id = R.string.music),
                modifier = Modifier
                    .size(42.dp)
                    .clickableCustomIndication() {
                        viewModel.pauseOrRestoreMusic()
                    },
                contentScale = ContentScale.Crop,
                error = painterResource(id = R.drawable.ic_not_photo)
            )
            CircularProgressIndicator(
                modifier = Modifier.size(44.dp),
                progress = viewModel.musicProcess,
//                progress = 0.5f,
                strokeWidth = 2.5.dp,
                color = PrimaryColor
            )
        }
    }
}